package coding

import (
	"coding.net/vco/mder/modules/log"
	"coding.net/vco/mder/modules/target"
	"coding.net/vco/mder/modules/util"
	"fmt"
	"github.com/Unknwon/com"

	"net/http"
	"os"
	"regexp"
	"strings"
)

const (
	web_hook_token = "WEBHOOK_TOKEN"
	DATA_PATH      = "blog"
	lang_markdown  = "markdown"
	static_dir     = "static"
)

//static dir ?
func IsStaticDir(dir string) bool {
	return dir == static_dir
}

var Ignores []string

//忽略
func IsIgnorable(path string) bool {

	return strings.HasPrefix(path, ".") || func() bool {
		for _, ig := range Ignores {

			if strings.HasPrefix(path, ig) {
				return true
			}
		}
		return false
	}()
}

//is folder ?
func isTree(mode string) bool {
	return mode == "tree"
}

//同步文件
func syncFile(path string, info CodingFile) {
	t := target.New()
	filePath := fmt.Sprintf("%s/%s", path, info.Name)
	fileUrl := util.FileBlobInfoUrl(t.GlobalKey, t.Project, filePath)
	fileResult := &CodingFileResult{}
	com.HttpGetJSON(&http.Client{}, fileUrl, fileResult)
	if fileResult.Success() {
		//不可预览
		dest := fmt.Sprintf("%s/%s", DATA_PATH, info.Path)

		if fileResult.Data.File.Data == "" && !fileResult.Data.File.Previewed { //不可预览,直接下载
			//不可预览按静态文件处理
			rawUrl := util.RawFileUrl(t.GlobalKey, t.Project, filePath)
			com.HttpGetToFile(&http.Client{}, rawUrl, nil, "static/"+info.Path)
		} else { //可预览
			com.WriteFile(dest, []byte(fileResult.Data.File.Data))
			if isMarkdownLang(fileResult.Data.File.Lang) {
				com.WriteFile(util.ToMdContent(dest), replaceCodingRelativePath(fileResult.Data.File.Preview)) //abc.md.mdc
				com.WriteFile(util.TdMdToml(dest), []byte(parseMdInfoStr(fileResult.Data.File.Data)))          //abc.md.mdt
			}
		}

	}
}

//markdown to html
//效果不是很理想
//u/vco/p/mder/git/raw/master/blog/assets/img/wall.png
func replaceCodingRelativePath(md string) []byte {
	t := target.New()
	raw := fmt.Sprintf("/u/%s/p/%s/git/raw/%s", t.GlobalKey, t.Project, t.Ref)
	return []byte(strings.Replace(md, raw, "", -1))
	//return blackfriday.MarkdownCommon([]byte(md))
}

func isMarkdownLang(lang string) bool {
	return lang == lang_markdown
}

func FetchMdFile(filePath string) {

	t := target.New()
	fileResult := &CodingFileResult{}
	fileUrl := util.FileBlobInfoUrl(t.GlobalKey, t.Project, filePath)
	com.HttpGetJSON(&http.Client{}, fileUrl, fileResult)
	if fileResult.Success() {
		dest := fmt.Sprintf("%s/%s", DATA_PATH, filePath)
		com.WriteFile(dest, []byte(fileResult.Data.File.Data))
		if isMarkdownLang(fileResult.Data.File.Lang) {
			com.WriteFile(util.ToMdContent(dest), replaceCodingRelativePath(fileResult.Data.File.Preview)) //abc.md.mdc
			com.WriteFile(util.TdMdToml(dest), []byte(parseMdInfoStr(fileResult.Data.File.Data)))          //abc.md.mdt
		}
	} else {
		log.Error("远程请 API(%s) 异常", fileUrl)
	}
}

func SyncPath(path string) {
	t := target.New()
	log.Debug("-----------path:", path)
	url := util.TreeInfoUrl(t.GlobalKey, t.Project, path)
	v := &CodingTreeResult{}
	com.HttpGetJSON(&http.Client{}, url, v)
	if v.success() {
		for _, info := range v.Data.Infos {
			if IsIgnorable(info.Path) {
				log.Debug("skip %s \n", info.Path)
				continue
			}

			if isTree(info.Mode) {
				SyncPath(fmt.Sprintf("%s/%s", t.Ref, info.Path))
			} else {
				//同步文件
				syncFile(path, info)
			}
		}
	} else {
		log.Error("远程请 API(%s) 异常", url)
	}
}

func parseMdInfoStr(content string) string {
	mdInfo := string(seoTomlReg.Find([]byte(content)))
	mdInfo = strings.Replace(mdInfo, "<!--", "", -1)
	mdInfo = strings.Replace(mdInfo, "-->", "", -1)
	return mdInfo
}

var seoTomlReg = regexp.MustCompile(`<!--[\w\W\r\n]*?-->`)

type CodingFileResult struct {
	Code int            `json:"code"`
	Data CodingFileData `json:"data"`
}

func (this CodingFileResult) Success() bool {
	return this.Code == 0
}

type CodingFileData struct {
	Can_edit bool       `json:"can_edit"`
	File     CodingFile `json:"file"`
	IsHead   bool       `json:"isHead"`
	Ref      string     `json:"ref"`
}

type CodingFile struct {
	Data              string         `json:"data"`
	Lang              string         `json:"lang"`
	LastCommitDate    int64          `json:"lastCommitDate"`
	LastCommitMessage string         `json:"lastCommitMessage"`
	LastCommitId      string         `json:"lastCommitId"`
	LastCommitter     CodingCommiter `json:"lastCommitter"`
	Mode              string         `json:"mode"` //file tree
	Name              string         `json:"name"`
	Path              string         `json:"path"`
	Preview           string         `json:"preview"`
	Size              int64          `json:"size"`
	Previewed         bool           `json:"previewed"`
}

//递交
type CodingCommiter struct {
	Avatar string `json:"avatar"`
	Email  string `json:"email"`
	Link   string `json:"link"`
	Name   string `json:"name"`
}

//coding 目录树
type CodingTreeResult struct {
	Code int            `json:"code"`
	Data CodingTreeData `json:"data"`
}

func (this CodingTreeResult) success() bool {
	return this.Code == 0
}

type CodingTreeData struct {
	Infos []CodingFile `json:"infos"`
}

//rebuild
//globalKey user
//project 项目
//ref 分支或标签
func Rebuild(globalkey, project, ref string) {
	clearPath(DATA_PATH)
	target.Set(globalkey, project, ref)
	SyncPath(ref)
}

func clearPath(root string) {
	//filepath.Walk(pa, func(){})
	paths, _ := com.GetAllSubDirs(root)
	for _, path := range paths {
		os.Remove(path)
	}
}

//globalKey
//project
func ParseRepository(url string) (string, string) {
	//https://coding.net/u/jiong/p/hello-coding/git
	//TODO regexp
	gStart := strings.Index(url, "/u/") + 3
	gEnd := strings.Index(url, "/p/") + 3
	pEnd := strings.Index(url, "/git")
	return url[gStart:strings.Index(url, "/p/")], url[gEnd:pEnd]
}

//不用配置target

type CodingPush struct {
	Zen        string
	After      string
	Before     string
	Ref        string
	Token      string
	Repository CodingRepository
	Commits    []CodingCommit
}

func (this CodingPush) ValidateToken() bool {
	return this.Token == os.Getenv(web_hook_token) && len(this.Token) > 0
}

type CodingRepository struct {
	Description string
	Name        string
	Url         string
}

type CodingCommit struct {
	Short_message string
	Sha           string
	Commiter      CodingCommiter
}

/*

{
    "after": "74e9f243b94dc4c9ab4db3d58d0994db0d62da51",  //推送之后的版本号
    "before": "36aa3b2a1aeddb8c05b3eabf606f9e083cfb0cac",  //推送之前的版本号
    "commits": [
        {
            "commiter": {  //提交者
                "email": "xxxxx@gmail.com",
                "name": "超级小胖"
            },
            "sha": "74e9f243b94dc4c9ab4db3d58d0994db0d62da51",
            "short_message": "update hello.md"
        }
    ],
    "ref": "master",  //当前提交的分支或标签名
    "repository": {
        "description": "",
        "name": "hello-coding",
        "url": "https://coding.net/u/jiong/p/hello-coding/git"
    },
    "token": "123"
}


*/
